{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "52545e6a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "import matplotlib.pyplot as plt\n",
    "from core.model import Model\n",
    "\n",
    "import json"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "2797ad65",
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_results(predicted_data, true_data):\n",
    "    fig = plt.figure(facecolor='white')\n",
    "    ax = fig.add_subplot(111)\n",
    "    ax.plot(true_data, label='True Data')\n",
    "    plt.plot(predicted_data, label='Prediction')\n",
    "    plt.legend()\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c4b0840c",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv('./data/sh600031.csv')  # 读取股票文件\n",
    "df.set_index('date', inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "439b183e",
   "metadata": {},
   "outputs": [],
   "source": [
    "df.drop(['volume'],axis=1,inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "588096bf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>open</th>\n",
       "      <th>high</th>\n",
       "      <th>low</th>\n",
       "      <th>close</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2003-07-03</th>\n",
       "      <td>23.00</td>\n",
       "      <td>23.00</td>\n",
       "      <td>20.10</td>\n",
       "      <td>21.30</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-04</th>\n",
       "      <td>21.30</td>\n",
       "      <td>22.18</td>\n",
       "      <td>21.05</td>\n",
       "      <td>21.84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-07</th>\n",
       "      <td>21.90</td>\n",
       "      <td>21.96</td>\n",
       "      <td>21.51</td>\n",
       "      <td>21.80</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-08</th>\n",
       "      <td>21.80</td>\n",
       "      <td>22.22</td>\n",
       "      <td>21.70</td>\n",
       "      <td>21.91</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-09</th>\n",
       "      <td>21.75</td>\n",
       "      <td>22.65</td>\n",
       "      <td>21.70</td>\n",
       "      <td>22.47</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             open   high    low  close\n",
       "date                                  \n",
       "2003-07-03  23.00  23.00  20.10  21.30\n",
       "2003-07-04  21.30  22.18  21.05  21.84\n",
       "2003-07-07  21.90  21.96  21.51  21.80\n",
       "2003-07-08  21.80  22.22  21.70  21.91\n",
       "2003-07-09  21.75  22.65  21.70  22.47"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8e91a869",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取DataFrame中的数据，形式为数组array形式\n",
    "values = df.values\n",
    "# 确保所有数据为float类型\n",
    "values = values.astype('float32')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fbdb18bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义series_to_supervised()函数\n",
    "# 将时间序列转换为监督学习问题\n",
    "def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):\n",
    "    \"\"\"\n",
    "    将时间序列框定为有监督的学习数据集。\n",
    "        论据：\n",
    "        数据：作为列表或NumPy数组的观察序列。\n",
    "        n_in：作为输入的滞后观测数（X）。\n",
    "        n_out：作为输出的观察数（y）。\n",
    "        dropnan：布尔值，决定是否删除具有NaN值的行。\n",
    "    返回：\n",
    "    pd.DataFrame(用于监督学习)\n",
    "    \"\"\"\n",
    "    n_vars = 1 if type(data) is list else data.shape[1]\n",
    "    df = pd.DataFrame(data)\n",
    "    cols, names = list(), list()\n",
    "    # input sequence (t-n, ... t-1)\n",
    "    for i in range(n_in, 0, -1):\n",
    "        cols.append(df.shift(i))\n",
    "        names += [('var%d(t-%d)' % (j + 1, i)) for j in range(n_vars)]\n",
    "    # forecast sequence (t, t+1, ... t+n)\n",
    "    for i in range(0, n_out):\n",
    "        cols.append(df.shift(-i))\n",
    "        if i == 0:\n",
    "            names += [('var%d(t)' % (j + 1)) for j in range(n_vars)]\n",
    "        else:\n",
    "            names += [('var%d(t+%d)' % (j + 1, i)) for j in range(n_vars)]\n",
    "    # put it all together\n",
    "    agg = pd.concat(cols, axis=1)\n",
    "    agg.columns = names\n",
    "    # drop rows with NaN values\n",
    "    if dropnan:\n",
    "        agg.dropna(inplace=True)\n",
    "    return agg"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b4599843",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将时间序列转换为监督学习问题\n",
    "reframed = series_to_supervised(values, 1, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "885302e4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>var1(t-1)</th>\n",
       "      <th>var2(t-1)</th>\n",
       "      <th>var3(t-1)</th>\n",
       "      <th>var4(t-1)</th>\n",
       "      <th>var1(t)</th>\n",
       "      <th>var2(t)</th>\n",
       "      <th>var3(t)</th>\n",
       "      <th>var4(t)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>23.000000</td>\n",
       "      <td>23.000000</td>\n",
       "      <td>20.100000</td>\n",
       "      <td>21.299999</td>\n",
       "      <td>21.299999</td>\n",
       "      <td>22.180000</td>\n",
       "      <td>21.049999</td>\n",
       "      <td>21.840000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>21.299999</td>\n",
       "      <td>22.180000</td>\n",
       "      <td>21.049999</td>\n",
       "      <td>21.840000</td>\n",
       "      <td>21.900000</td>\n",
       "      <td>21.959999</td>\n",
       "      <td>21.510000</td>\n",
       "      <td>21.799999</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>21.900000</td>\n",
       "      <td>21.959999</td>\n",
       "      <td>21.510000</td>\n",
       "      <td>21.799999</td>\n",
       "      <td>21.799999</td>\n",
       "      <td>22.219999</td>\n",
       "      <td>21.700001</td>\n",
       "      <td>21.910000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>21.799999</td>\n",
       "      <td>22.219999</td>\n",
       "      <td>21.700001</td>\n",
       "      <td>21.910000</td>\n",
       "      <td>21.750000</td>\n",
       "      <td>22.650000</td>\n",
       "      <td>21.700001</td>\n",
       "      <td>22.469999</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>21.750000</td>\n",
       "      <td>22.650000</td>\n",
       "      <td>21.700001</td>\n",
       "      <td>22.469999</td>\n",
       "      <td>22.330000</td>\n",
       "      <td>22.910000</td>\n",
       "      <td>22.299999</td>\n",
       "      <td>22.650000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   var1(t-1)  var2(t-1)  var3(t-1)  var4(t-1)    var1(t)    var2(t)  \\\n",
       "1  23.000000  23.000000  20.100000  21.299999  21.299999  22.180000   \n",
       "2  21.299999  22.180000  21.049999  21.840000  21.900000  21.959999   \n",
       "3  21.900000  21.959999  21.510000  21.799999  21.799999  22.219999   \n",
       "4  21.799999  22.219999  21.700001  21.910000  21.750000  22.650000   \n",
       "5  21.750000  22.650000  21.700001  22.469999  22.330000  22.910000   \n",
       "\n",
       "     var3(t)    var4(t)  \n",
       "1  21.049999  21.840000  \n",
       "2  21.510000  21.799999  \n",
       "3  21.700001  21.910000  \n",
       "4  21.700001  22.469999  \n",
       "5  22.299999  22.650000  "
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reframed.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "50b4dee4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 删除不想预测的特征列，这里只预测收盘价\n",
    "# 所以删除的是var1(t),var2(t),var3(t),\n",
    "reframed.drop(['var1(t)', 'var2(t)', 'var3(t)'], axis=1, inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b79f0d7a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>var1(t-1)</th>\n",
       "      <th>var2(t-1)</th>\n",
       "      <th>var3(t-1)</th>\n",
       "      <th>var4(t-1)</th>\n",
       "      <th>var4(t)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>23.000000</td>\n",
       "      <td>23.000000</td>\n",
       "      <td>20.100000</td>\n",
       "      <td>21.299999</td>\n",
       "      <td>21.840000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>21.299999</td>\n",
       "      <td>22.180000</td>\n",
       "      <td>21.049999</td>\n",
       "      <td>21.840000</td>\n",
       "      <td>21.799999</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>21.900000</td>\n",
       "      <td>21.959999</td>\n",
       "      <td>21.510000</td>\n",
       "      <td>21.799999</td>\n",
       "      <td>21.910000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>21.799999</td>\n",
       "      <td>22.219999</td>\n",
       "      <td>21.700001</td>\n",
       "      <td>21.910000</td>\n",
       "      <td>22.469999</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>21.750000</td>\n",
       "      <td>22.650000</td>\n",
       "      <td>21.700001</td>\n",
       "      <td>22.469999</td>\n",
       "      <td>22.650000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   var1(t-1)  var2(t-1)  var3(t-1)  var4(t-1)    var4(t)\n",
       "1  23.000000  23.000000  20.100000  21.299999  21.840000\n",
       "2  21.299999  22.180000  21.049999  21.840000  21.799999\n",
       "3  21.900000  21.959999  21.510000  21.799999  21.910000\n",
       "4  21.799999  22.219999  21.700001  21.910000  22.469999\n",
       "5  21.750000  22.650000  21.700001  22.469999  22.650000"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reframed.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "91d4be5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 划分训练集和测试集\n",
    "train = reframed.iloc[:int(len(reframed) * 0.85), :].values\n",
    "test = reframed.iloc[int(len(reframed) * 0.85):, :].values\n",
    "# 划分训练集和测试集的输入和输出\n",
    "train_X, train_y = train[:, :-1], train[:, -1]\n",
    "test_X, test_y = test[:, :-1], test[:, -1]\n",
    "# 转化为三维数据\n",
    "# reshape input to be 3D [samples, timesteps, features]\n",
    "train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))\n",
    "test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "474b0179",
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "configs = json.load(open('./test_1/config.json', 'r'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "baa20f5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Model] Model Compiled\n",
      "Time taken: 0:00:01.015917\n"
     ]
    }
   ],
   "source": [
    "model = Model()\n",
    "model.build_model(configs, train_X.shape[1], train_X.shape[2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "8eaa9e30",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Model] Training Started\n",
      "[Model] 50 epochs, 64 batch size\n",
      "Epoch 1/50\n",
      "59/59 [==============================] - 10s 43ms/step - loss: 299.4852 - val_loss: 156.6487\n",
      "Epoch 2/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 143.6328 - val_loss: 95.6540\n",
      "Epoch 3/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 89.4762 - val_loss: 54.0653\n",
      "Epoch 4/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 63.8508 - val_loss: 32.0166\n",
      "Epoch 5/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 47.1594 - val_loss: 20.1891\n",
      "Epoch 6/50\n",
      "59/59 [==============================] - 1s 16ms/step - loss: 37.1992 - val_loss: 13.1035\n",
      "Epoch 7/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 29.6858 - val_loss: 9.1565\n",
      "Epoch 8/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 25.0098 - val_loss: 6.9987\n",
      "Epoch 9/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 20.6006 - val_loss: 5.2019\n",
      "Epoch 10/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 17.5901 - val_loss: 4.4941\n",
      "Epoch 11/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 15.9678 - val_loss: 2.7917\n",
      "Epoch 12/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 14.0695 - val_loss: 3.9232\n",
      "Epoch 13/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 11.9319 - val_loss: 1.8935\n",
      "Epoch 14/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 10.5789 - val_loss: 3.1987\n",
      "Epoch 15/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 9.6097 - val_loss: 1.6581\n",
      "Epoch 16/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 8.7812 - val_loss: 1.7817\n",
      "Epoch 17/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 7.8552 - val_loss: 0.8909\n",
      "Epoch 18/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 7.5471 - val_loss: 1.7355\n",
      "Epoch 19/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 6.6670 - val_loss: 1.2891\n",
      "Epoch 20/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 6.7070 - val_loss: 0.8791\n",
      "Epoch 21/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 6.0109 - val_loss: 3.9485\n",
      "Epoch 22/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 5.6687 - val_loss: 0.6788\n",
      "Epoch 23/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 5.4408 - val_loss: 1.3129\n",
      "Epoch 24/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 5.1737 - val_loss: 3.4092\n",
      "Epoch 25/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 4.6654 - val_loss: 1.3261\n",
      "Epoch 26/50\n",
      "59/59 [==============================] - 1s 17ms/step - loss: 4.4023 - val_loss: 2.4126\n",
      "Epoch 27/50\n",
      "59/59 [==============================] - 1s 16ms/step - loss: 4.4556 - val_loss: 1.2503\n",
      "Epoch 28/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 4.2193 - val_loss: 1.9995\n",
      "Epoch 29/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 4.5988 - val_loss: 1.8288\n",
      "Epoch 30/50\n",
      "59/59 [==============================] - 1s 13ms/step - loss: 3.9164 - val_loss: 0.7974\n",
      "Epoch 31/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 3.7421 - val_loss: 0.5421\n",
      "Epoch 32/50\n",
      "59/59 [==============================] - 1s 16ms/step - loss: 3.9171 - val_loss: 0.6923\n",
      "Epoch 33/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.9089 - val_loss: 1.0603\n",
      "Epoch 34/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.5243 - val_loss: 1.1353\n",
      "Epoch 35/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.2789 - val_loss: 1.8977\n",
      "Epoch 36/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.2116 - val_loss: 1.5325\n",
      "Epoch 37/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 3.7429 - val_loss: 1.1953\n",
      "Epoch 38/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 3.4242 - val_loss: 1.2260\n",
      "Epoch 39/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.3027 - val_loss: 0.8230\n",
      "Epoch 40/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.5471 - val_loss: 0.6146\n",
      "Epoch 41/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 3.4951 - val_loss: 2.4404\n",
      "Epoch 42/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.9199 - val_loss: 0.8558\n",
      "Epoch 43/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.1643 - val_loss: 1.0171\n",
      "Epoch 44/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.7396 - val_loss: 1.4006\n",
      "Epoch 45/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.2886 - val_loss: 1.1377\n",
      "Epoch 46/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 3.1533 - val_loss: 0.5984\n",
      "Epoch 47/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 3.0780 - val_loss: 0.6823\n",
      "Epoch 48/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.2304 - val_loss: 1.3257\n",
      "Epoch 49/50\n",
      "59/59 [==============================] - 1s 15ms/step - loss: 3.4744 - val_loss: 1.3917\n",
      "Epoch 50/50\n",
      "59/59 [==============================] - 1s 14ms/step - loss: 4.0159 - val_loss: 0.6420\n",
      "[Model] Training Completed. Model saved as save_models\n",
      "Time taken: 0:00:52.695647\n"
     ]
    }
   ],
   "source": [
    "# 内存中训练\n",
    "model.train(\n",
    "    train_X,\n",
    "    train_y,\n",
    "    epochs=configs['training']['epochs'],\n",
    "    batch_size=configs['training']['batch_size'],\n",
    "    validation_data=(test_X, test_y),\n",
    "    verbose=configs['training']['verbose'],\n",
    "    shuffle=configs['training']['shuffle'],\n",
    "    validation_freq=configs['training']['validation_freq'],\n",
    "    save_dir=configs['model']['save_dir']\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "cacd9cda",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Model] Predicting Point-by-Point...\n"
     ]
    }
   ],
   "source": [
    "y_predict = model.predict_point_by_point(test_X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "b07b62fd",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_y = test_y.reshape((len(test_y), 1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "2987243d",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_results(y_predict, test_y)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "deep",
   "language": "python",
   "name": "deep"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
